<template>
  <div class="chat-message-list">
    <template v-for="(message, index) in messages" :key="message.id">
      <!-- 显示日期分隔线 -->
      <div class="date-divider" v-if="shouldShowDate(message, index)">
        <div class="date-line"></div>
        <div class="date-content">{{ formatDate(message.created_at) }}</div>
        <div class="date-line"></div>
      </div>
      
      <!-- 消息内容 -->
      <div 
        class="message-container" 
        :class="{ 
          'user-message': message.role === 'user', 
          'ai-message': message.role === 'ai' 
        }"
      >
        <!-- 头像 -->
        <div class="avatar-container">
          <div class="avatar">
            <template v-if="message.role === 'user'">
              <i class="fa fa-user"></i>
            </template>
            <template v-else>
              <i class="fa fa-robot"></i>
            </template>
          </div>
        </div>
        
        <!-- 消息内容 -->
        <div class="message-content">
          <!-- 时间戳 -->
          <div class="message-time" v-if="shouldShowTime(message, index)">
            {{ formatMessageTime(message.created_at) }}
          </div>
          
          <!-- 消息气泡 -->
          <div 
            class="message-bubble" 
            :class="{ 
              'error-message': message.error,
              'system-message': message.role === 'system'
            }"
          >
            <!-- 网络搜索标记 -->
            <div class="web-search-badge" v-if="message.web_search">
              <i class="fa fa-globe"></i> 网络搜索已启用
            </div>
            
            <!-- 文本内容 -->
            <div 
              class="message-text" 
              v-html="formatMessage(message.content)"
            ></div>
            
            <!-- 附件展示 -->
            <div class="attachments" v-if="message.attachments && message.attachments.length > 0">
              <div 
                v-for="(attachment, aIndex) in message.attachments" 
                :key="aIndex"
                class="attachment"
                @click="previewAttachment(attachment)"
              >
                <template v-if="isImage(attachment)">
                  <div class="image-attachment">
                    <img 
                      :src="attachment.url || attachment.thumbnail_url" 
                      :alt="attachment.filename"
                    />
                  </div>
                </template>
                <template v-else>
                  <div class="file-attachment">
                    <i class="fa fa-file-text-o"></i>
                    <div class="file-info">
                      <div class="file-name" :title="attachment.filename">
                        {{ attachment.filename }}
                      </div>
                      <div class="file-size">
                        {{ formatFileSize(attachment.size) }}
                      </div>
                    </div>
                  </div>
                </template>
              </div>
            </div>
            
            <!-- 引用链接 -->
            <div class="references" v-if="message.references && message.references.length > 0">
              <div class="references-title">
                <i class="fa fa-link"></i> 引用来源
              </div>
              <div 
                v-for="(reference, rIndex) in message.references" 
                :key="rIndex"
                class="reference-item"
              >
                <a :href="reference.url" target="_blank" rel="noopener noreferrer">
                  {{ reference.title || reference.url }}
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <!-- AI正在输入提示 -->
    <div class="message-container ai-message" v-if="typing">
      <div class="avatar-container">
        <div class="avatar">
          <i class="fa fa-robot"></i>
        </div>
      </div>
      
      <div class="message-content">
        <div class="message-bubble typing-indicator">
          <div class="typing-dots">
            <span></span>
            <span></span>
            <span></span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed } from 'vue';
import DOMPurify from 'dompurify';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';

dayjs.locale('zh-cn');

// 定义属性
const props = defineProps({
  messages: {
    type: Array,
    default: () => []
  },
  typing: {
    type: Boolean,
    default: false
  }
});

// 定义事件
const emit = defineEmits(['preview-attachment']);

// 是否显示日期分隔线
function shouldShowDate(message, index) {
  if (index === 0) return true;
  
  const currentDate = dayjs(message.created_at).startOf('day');
  const prevDate = dayjs(props.messages[index - 1].created_at).startOf('day');
  
  return !currentDate.isSame(prevDate);
}

// 是否显示时间
function shouldShowTime(message, index) {
  // 第一条消息显示时间
  if (index === 0) return true;
  
  const currentTime = dayjs(message.created_at);
  const prevTime = dayjs(props.messages[index - 1].created_at);
  
  // 如果距离上一条消息超过5分钟，显示时间
  return currentTime.diff(prevTime, 'minute') > 5;
}

// 格式化日期
function formatDate(timeString) {
  if (!timeString) return '';
  
  const date = dayjs(timeString);
  const now = dayjs();
  
  // 今天
  if (date.isSame(now, 'day')) {
    return '今天';
  }
  
  // 昨天
  if (date.isSame(now.subtract(1, 'day'), 'day')) {
    return '昨天';
  }
  
  // 本周内
  if (date.isAfter(now.startOf('week'))) {
    return date.format('dddd');
  }
  
  // 本年内
  if (date.isSame(now, 'year')) {
    return date.format('M月D日');
  }
  
  // 其他
  return date.format('YYYY年M月D日');
}

// 格式化消息时间
function formatMessageTime(timeString) {
  if (!timeString) return '';
  
  return dayjs(timeString).format('HH:mm');
}

// 格式化消息内容
function formatMessage(content) {
  if (!content || typeof content !== 'string') return '';
  
  // 转换换行符为<br>
  const withLineBreaks = content.replace(/\n/g, '<br>');
  
  // 使用DOMPurify防止XSS攻击
  return DOMPurify.sanitize(withLineBreaks);
}

// 判断是否为图片
function isImage(attachment) {
  if (!attachment) return false;
  
  if (attachment.mime_type) {
    return attachment.mime_type.startsWith('image/');
  }
  
  if (attachment.filename) {
    const ext = attachment.filename.split('.').pop().toLowerCase();
    return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'].includes(ext);
  }
  
  return false;
}

// 预览附件
function previewAttachment(attachment) {
  emit('preview-attachment', attachment);
}

// 格式化文件大小
function formatFileSize(bytes) {
  if (!bytes) return '0 B';
  if (bytes < 1024) return bytes + ' B';
  else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
  else if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
  else return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
}
</script>

<style scoped>
.chat-message-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* 日期分隔线 */
.date-divider {
  display: flex;
  align-items: center;
  margin: 16px 0;
  color: #909399;
  font-size: 12px;
}

.date-line {
  flex: 1;
  height: 1px;
  background-color: #ebeef5;
}

.date-content {
  padding: 0 12px;
}

/* 消息容器 */
.message-container {
  display: flex;
  margin-bottom: 8px;
}

.user-message {
  flex-direction: row-reverse;
}

/* 头像 */
.avatar-container {
  flex-shrink: 0;
  margin: 0 8px;
}

.avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

.user-message .avatar {
  background-color: #ecf5ff;
  color: #409eff;
}

.ai-message .avatar {
  background-color: #f0f9eb;
  color: #67c23a;
}

/* 消息内容 */
.message-content {
  max-width: 80%;
  display: flex;
  flex-direction: column;
}

.message-time {
  font-size: 12px;
  color: #909399;
  margin-bottom: 4px;
  text-align: center;
}

.message-bubble {
  padding: 10px 16px;
  border-radius: 12px;
  position: relative;
  word-wrap: break-word;
  white-space: pre-wrap;
}

.user-message .message-bubble {
  background-color: #409eff;
  color: #fff;
  border-bottom-right-radius: 4px;
}

.ai-message .message-bubble {
  background-color: #f5f7fa;
  color: #303133;
  border-bottom-left-radius: 4px;
}

.error-message {
  background-color: #fef0f0 !important;
  color: #f56c6c !important;
  border: 1px solid #fbc4c4;
}

.system-message {
  background-color: #f0f9eb !important;
  color: #67c23a !important;
  font-style: italic;
}

.message-text {
  line-height: 1.5;
  font-size: 14px;
}

/* 附件样式 */
.attachments {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.attachment {
  cursor: pointer;
  border-radius: 8px;
  overflow: hidden;
  background-color: rgba(255, 255, 255, 0.1);
  transition: transform 0.2s;
}

.attachment:hover {
  transform: scale(1.02);
}

.image-attachment {
  width: 150px;
  height: 100px;
  overflow: hidden;
}

.image-attachment img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.file-attachment {
  width: 200px;
  display: flex;
  align-items: center;
  padding: 8px 12px;
  background-color: rgba(255, 255, 255, 0.15);
}

.user-message .file-attachment {
  background-color: rgba(0, 0, 0, 0.1);
}

.ai-message .file-attachment {
  background-color: rgba(0, 0, 0, 0.05);
}

.file-attachment i {
  font-size: 24px;
  margin-right: 10px;
}

.file-info {
  flex: 1;
  min-width: 0;
}

.file-name {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-size {
  font-size: 11px;
  opacity: 0.8;
  margin-top: 2px;
}

/* 引用链接 */
.references {
  margin-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 8px;
}

.ai-message .references {
  border-top-color: rgba(0, 0, 0, 0.1);
}

.references-title {
  font-size: 12px;
  margin-bottom: 4px;
  opacity: 0.8;
}

.reference-item {
  font-size: 12px;
  margin-bottom: 2px;
}

.reference-item a {
  color: inherit;
  text-decoration: underline;
  opacity: 0.8;
}

.reference-item a:hover {
  opacity: 1;
}

/* 网络搜索标记 */
.web-search-badge {
  display: inline-block;
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 4px;
  margin-bottom: 6px;
  background-color: rgba(0, 0, 0, 0.1);
}

.user-message .web-search-badge {
  background-color: rgba(255, 255, 255, 0.2);
}

/* 打字机动画 */
.typing-indicator {
  padding: 12px 16px;
  display: flex;
  align-items: center;
}

.typing-dots {
  display: flex;
  align-items: center;
}

.typing-dots span {
  height: 8px;
  width: 8px;
  border-radius: 50%;
  background-color: #909399;
  margin-right: 4px;
  animation: typing 1s infinite ease-in-out;
}

.typing-dots span:nth-child(1) {
  animation-delay: 0s;
}

.typing-dots span:nth-child(2) {
  animation-delay: 0.2s;
}

.typing-dots span:nth-child(3) {
  animation-delay: 0.4s;
  margin-right: 0;
}

@keyframes typing {
  0% {
    transform: scale(1);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.2);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 0.7;
  }
}
</style> 